1 25개 자치구 데이터

  • 서울특별시
    • 25개 자치구
    • 424개 행정동

1.1 .지도

### 시도

sido_sf_raw <- sf::st_read("../../docs/election_map/data/map/CTPRVN_202101/TL_SCCO_CTPRVN.shp")
Reading layer `TL_SCCO_CTPRVN' from data source 
  `C:\docs\election_map\data\map\CTPRVN_202101\TL_SCCO_CTPRVN.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 17 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 746110.3 ymin: 1458754 xmax: 1387950 ymax: 2068444
Projected CRS: PCS_ITRF2000_TM
seoul_sido_code <- sido_sf_raw %>% 
  mutate(CTP_KOR_NM = iconv(CTP_KOR_NM, from = "CP949", to = "UTF-8", toRaw = FALSE)) %>% 
  filter( str_detect(CTP_KOR_NM, "서울") ) %>% 
  pull(CTPRVN_CD)

### 서울특별시

sigungu_sf_raw <- sf::st_read("../../docs/election_map/data/map/SIG_202101/TL_SCCO_SIG.shp")
Reading layer `TL_SCCO_SIG' from data source 
  `C:\docs\election_map\data\map\SIG_202101\TL_SCCO_SIG.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 250 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 746110.3 ymin: 1458754 xmax: 1387948 ymax: 2068444
Projected CRS: PCS_ITRF2000_TM
sigungu_seoul_sf <- sigungu_sf_raw %>% 
  mutate(SIG_KOR_NM = iconv(SIG_KOR_NM, from = "CP949", to = "UTF-8", toRaw = FALSE)) %>% 
  mutate(CTP_KOR_NM = str_sub(SIG_CD, 1, 2)) %>% 
  filter(CTP_KOR_NM == seoul_sido_code) %>% 
  mutate(sgg_code = str_sub(SIG_CD, 1, 4)) %>% 
  st_simplify(dTolerance = 100, preserveTopology = TRUE)

pryr::object_size(sigungu_seoul_sf)
37,136 B
sigungu_seoul_sf %>% 
  plot()

1.2 .육각형 지도

seoul_hex <- calculate_grid(shape = sigungu_seoul_sf, grid_type = "hexagonal", seed = 3)
seoul_hex_map_raw <- assign_polygons(sigungu_seoul_sf, seoul_hex)


seoul_hex_map <- seoul_hex_map_raw %>%
  dplyr::select(SIG_KOR_NM) %>% 
  mutate(SIG_KOR_NM = stringi::stri_escape_unicode(SIG_KOR_NM))


seoul_hex_map %>%
  st_write("data/tilemap/seoul_hex_map.shp",
           delete_layer=TRUE, overwrite=TRUE)
Deleting layer `seoul_hex_map' using driver `ESRI Shapefile'
Writing layer `seoul_hex_map' to data source 
  `data/tilemap/seoul_hex_map.shp' using driver `ESRI Shapefile'
Writing 25 features with 1 fields and geometry type Polygon.

1.3 .지도 시각화

seoul_hex_map <- 
  st_read("data/tilemap/seoul_hex_map.shp") %>% 
  mutate(SIG_KOR_NM = stringi::stri_unescape_unicode(SIG_KOR_NM))
Reading layer `seoul_hex_map' from data source 
  `C:\swc\local\data\tilemap\seoul_hex_map.shp' using driver `ESRI Shapefile'
Simple feature collection with 25 features and 1 field
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 936743 ymin: 1939324 xmax: 972635.9 ymax: 1967448
Projected CRS: PCS_ITRF2000_TM
seoul_hex_map %>% 
  ggplot() +
    geom_sf() +
    geom_sf_text(aes(geometry = geometry, label = SIG_KOR_NM), 
            fun.geometry = function(x) st_centroid(x) ) +
    theme_void()

2 자치구 마포구 동 데이터

  • 서울특별시
    • 25개 자치구
    • 424개 행정동

마포구 행정구역: 26개의 법정동을 16개의 행정이 관할

2.1 .마포구 지도

SHP_code <- 
  read_rds("data/SHP_code.rds")

mapo_gu_code <- SHP_code %>% 
  filter(str_detect(CTP_KOR_NM, "서울"),
         str_detect(SIG_KOR_NM, "마포"))
  


### 읍면동

emd_sf_raw <- sf::st_read("../../docs/election_map/data/map/EMD_202101/TL_SCCO_EMD.shp")
Reading layer `TL_SCCO_EMD' from data source 
  `C:\docs\election_map\data\map\EMD_202101\TL_SCCO_EMD.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 5051 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 746110.3 ymin: 1458754 xmax: 1387948 ymax: 2068444
Projected CRS: PCS_ITRF2000_TM
mapo_gu_sf <- emd_sf_raw %>% 
  mutate(EMD_KOR_NM = iconv(EMD_KOR_NM, from = "CP949", to = "UTF-8", toRaw = FALSE)) %>% 
  inner_join(mapo_gu_code) %>% 
  st_simplify(dTolerance = 50, preserveTopology = TRUE)



pryr::object_size(mapo_gu_sf)
29,400 B
mapo_gu_sf %>% 
  plot()

2.2 .마포구 육각형 지도

mapo_hex <- calculate_grid(shape = mapo_gu_sf, grid_type = "hexagonal", seed = 3)
mapo_hex_map_raw <- assign_polygons(mapo_gu_sf, mapo_hex)


mapo_hex_map <- mapo_hex_map_raw %>%
  dplyr::select(SIG_KOR_NM, EMD_KOR_NM) %>% 
  mutate(SIG_KOR_NM = stringi::stri_escape_unicode(SIG_KOR_NM),
         EMD_KOR_NM = stringi::stri_escape_unicode(EMD_KOR_NM))


mapo_hex_map %>%
  st_write("data/tilemap/mapo_hex_map.shp",
           delete_layer=TRUE, overwrite=TRUE)
Deleting layer `mapo_hex_map' using driver `ESRI Shapefile'
Writing layer `mapo_hex_map' to data source 
  `data/tilemap/mapo_hex_map.shp' using driver `ESRI Shapefile'
Writing 26 features with 2 fields and geometry type Polygon.

2.3 .마포구 지도 시각화

mapo_hex_map  <- 
  st_read("data/tilemap/mapo_hex_map.shp") %>% 
  mutate(SIG_KOR_NM = stringi::stri_unescape_unicode(SIG_KOR_NM),
         EMD_KOR_NM = stringi::stri_unescape_unicode(EMD_KOR_NM))
Reading layer `mapo_hex_map' from data source 
  `C:\swc\local\data\tilemap\mapo_hex_map.shp' using driver `ESRI Shapefile'
Simple feature collection with 26 features and 2 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 943022.4 ymin: 1948946 xmax: 952539.5 ymax: 1954441
Projected CRS: PCS_ITRF2000_TM
mapo_hex_map %>% 
  ggplot() +
    geom_sf() +
    geom_sf_text(aes(geometry = geometry, label = EMD_KOR_NM), 
            fun.geometry = function(x) st_centroid(x) ) +
    theme_void()

2.4 .마포구 지도 + 대선

mapo_vote_tbl <- krvote::election_20220309$득표율 %>% 
  filter(str_detect(시도명, "서울"),
         str_detect(구시군명, "마포")) %>% 
  group_by(구시군명, 읍면동명) %>% 
  summarise(더불어민주당이재명 = sum(더불어민주당이재명),
            국민의힘윤석열 = sum(국민의힘윤석열),
            정의당심상정 = sum(정의당심상정),
= sum(계)) %>% 
  ungroup() %>% 
  mutate(이재명=더불어민주당이재명/계,
         윤석열=국민의힘윤석열/계,
         심상정=정의당심상정/계) %>% 
  filter(!str_detect(읍면동명, "거소|잘못")) %>% 
  mutate(득표율차이 = 이재명 - 윤석열)

mapo_vote_tbl
# A tibble: 18 x 10
   구시군명 읍면동명  더불어민주당이재~ 국민의힘윤석열 정의당심상정    계 이재명
   <chr>    <chr>                 <dbl>          <dbl>        <dbl> <dbl>  <dbl>
 1 마포구   공덕동                 8282           9631          598 18640  0.444
 2 마포구   관외사전~             17027          15755         1322 34402  0.495
 3 마포구   대흥동                 3417           4136          281  7900  0.433
 4 마포구   도화동                 5842           8017          443 14404  0.406
 5 마포구   망원1동                6625           5526          562 12835  0.516
 6 마포구   망원2동                5998           4795          424 11313  0.530
 7 마포구   상암동                 8544           8098          597 17371  0.492
 8 마포구   서강동                 6603           8191          558 15451  0.427
 9 마포구   서교동                 6412           6447          614 13591  0.472
10 마포구   성산1동                5762           4703          502 11076  0.520
11 마포구   성산2동               10423           9929          757 21287  0.490
12 마포구   신수동                 5284           6745          402 12525  0.422
13 마포구   아현동                 6000           8881          465 15422  0.389
14 마포구   연남동                 4730           4471          442  9752  0.485
15 마포구   염리동                 4445           5324          309 10148  0.438
16 마포구   용강동                 5222           7015          376 12697  0.411
17 마포구   재외투표               1339            919           89  2354  0.569
18 마포구   합정동                 5808           5536          559 12008  0.484
# ... with 3 more variables: 윤석열 <dbl>, 심상정 <dbl>, 득표율차이 <dbl>
mapo_vote_sf_tbl <- mapo_vote_tbl %>% 
  filter(! 읍면동명 %in% c("관외사전투표", "재외투표")) %>% 
  mutate(EMD_KOR_NM = case_when(str_detect(읍면동명, "망원") ~ "망원동",
                                str_detect(읍면동명, "성산") ~ "성산",
                                TRUE ~ 읍면동명
                                ) )

mapo_hex_map %>% 
  left_join(mapo_vote_sf_tbl, by = c("EMD_KOR_NM" = "EMD_KOR_NM")) %>% 
  ggplot() +
    geom_sf() +
    geom_sf_text(aes(geometry = geometry, label = glue::glue("{EMD_KOR_NM}\n{scales::percent(득표율차이, accuracy = 0.1)}") ), 
            fun.geometry = function(x) st_centroid(x) ) +
    theme_void()

mapo_hex_map %>% 
  pull(EMD_KOR_NM)
 [1] "마포동"   "토정동"   "용강동"   "도화동"   "신공덕동" "합정동"  
 [7] "신정동"   "구수동"   "신수동"   "대흥동"   "당인동"   "현석동"  
[13] "상수동"   "창전동"   "염리동"   "하중동"   "망원동"   "서교동"  
[19] "동교동"   "노고산동" "공덕동"   "상암동"   "성산동"   "연남동"  
[25] "중동"     "아현동"  

3 geojson 마포구 동 데이터

precinct_sf <- st_read("data/tilemap/HangJeongDong_ver20220309.geojson")

mapo_geojson <- precinct_sf  %>% 
  filter(str_detect(ELEC_SIDO, "서울"),
         str_detect(ELEC_GU, "마포") )

mapo_dong_g <- mapo_geojson %>% 
  select(ELEC_SIDO, ELEC_GU, ELEC_EMD) %>% 
  left_join(mapo_vote_tbl %>% filter(! 읍면동명 %in% c("관외사전투표", "재외투표")), by = c("ELEC_EMD" = "읍면동명")) %>% 
  ggplot() +
    geom_sf(aes(geometry = geometry, fill = 득표율차이)) +
    geom_sf_text(aes(geometry = geometry, label = glue::glue("{ELEC_EMD}\n{scales::percent(득표율차이, accuracy = 0.1)}") ), 
            fun.geometry = function(x) st_centroid(x) ) +
    theme_void() +
        scale_fill_gradientn( colours = c("red", "white", "blue"), labels = scales::percent) +
    labs(
      title = "제20대 대통령선거 서울특별시",
      subtitle = "마포구 동별 득표율 차이: 이재명(%) - 윤석열(%)",
      fill = "득표율 차이(%)",
      caption = "데이터출처: 중앙선거관리위원회 선거통계시스템"
    ) +
    theme(
      text = element_text(family = "NanumBarunpen"),
      plot.tag.position = c(0.85, .97),
      legend.position = "right",
      legend.title=element_text(size=15), 
      legend.key.size = unit(1.5, 'cm'),
      legend.text=element_text(size=13),
      plot.title=element_text(size=25, face="bold", family = "NanumBarunpen"),
      plot.subtitle=element_text(face="bold", size=17, colour="grey10", family = "NanumBarunpen"))     

mapo_dong_g

ragg::agg_png("fig/mapo_dong_g.png", width = 297, height = 210, units = "mm", res = 600, scaling = 0.85)
mapo_dong_g
dev.off()

4 geojson –> 육각형 지도

mapo_hex <- calculate_grid(shape = mapo_geojson, grid_type = "hexagonal", seed = 3)
mapo_hex_map_raw <- assign_polygons(mapo_geojson, mapo_hex)


mapo_hex_map <- mapo_hex_map_raw %>%
  dplyr::select(ELEC_GU, ELEC_EMD) %>% 
  mutate(ELEC_GU = stringi::stri_escape_unicode(ELEC_GU),
         ELEC_EMD = stringi::stri_escape_unicode(ELEC_EMD))

mapo_hex_map %>%
  st_write("data/tilemap/mapo_hex_map.shp",
           delete_layer=TRUE, overwrite=TRUE)
mapo_hex_map  <- 
  st_read("data/tilemap/mapo_hex_map.shp") %>% 
  mutate(ELEC_GU = stringi::stri_unescape_unicode(ELEC_GU),
         ELEC_EMD = stringi::stri_unescape_unicode(ELEC_EMD))

mapo_dong_hex_g <- mapo_hex_map %>% 
  select(ELEC_GU, ELEC_EMD) %>% 
  left_join(mapo_vote_tbl %>% filter(! 읍면동명 %in% c("관외사전투표", "재외투표")), by = c("ELEC_EMD" = "읍면동명")) %>% 
  ggplot() +
    geom_sf(aes(geometry = geometry, fill = 득표율차이)) +
    geom_sf_text(aes(geometry = geometry, label = glue::glue("{ELEC_EMD}\n{scales::percent(득표율차이, accuracy = 0.1)}") ), 
            fun.geometry = function(x) st_centroid(x) ) +
    theme_void() +
        scale_fill_gradientn( colours = c("red", "white", "blue"), labels = scales::percent) +
    labs(
      title = "제20대 대통령선거 서울특별시",
      subtitle = "마포구 동별 득표율 차이: 이재명(%) - 윤석열(%)",
      fill = "득표율 차이(%)",
      caption = "데이터출처: 중앙선거관리위원회 선거통계시스템"
    ) +
    theme(
      text = element_text(family = "NanumBarunpen"),
      plot.tag.position = c(0.85, .97),
      legend.position = "right",
      legend.title=element_text(size=15), 
      legend.key.size = unit(1.5, 'cm'),
      legend.text=element_text(size=13),
      plot.title=element_text(size=25, face="bold", family = "NanumBarunpen"),
      plot.subtitle=element_text(face="bold", size=17, colour="grey10", family = "NanumBarunpen"))

mapo_dong_hex_g

ragg::agg_png("fig/mapo_dong_hex_g.png", width = 297, height = 210, units = "mm", res = 600, scaling = 0.85)
mapo_dong_hex_g
dev.off()

library(patchwork)

mapo_dong_g + mapo_dong_hex_g

ragg::agg_png("fig/mapo_dong_original_hex_g.png", width = 297, height = 210, units = "mm", res = 600, scaling = 0.85)
mapo_dong_g + mapo_dong_hex_g
dev.off()

 

데이터 과학자 이광춘 저작

kwangchun.lee.7@gmail.com